/*
 * @Author: zi.yang
 * @Date: 2020-06-18 12:14:40
 * @LastEditTime: 2021-10-05 15:07:51
 * @LastEditors: zi.yang
 * @Description: 用户信息
 * @FilePath: \project-management\services\SysUser.js
 */
const moment = require('moment');
const JwtUtil = require('../utils/jwt');
const SysUser = require('../models/sys_users');
const SysLoginLog = require('./SysLoginLog');
const encryption = require('../utils/encryption');
const ormErrorMessage = require('../utils/ormErrorMessage');
const { Op } = require('sequelize');
const ep = new encryption();

/**
 * @description:  获取所有用户信息
 * @param { function } cb
 * @return: cb()
 */
exports.findUserInfo = async function (cb) {
  try {
    const userInfo = await SysUser.findAll();
    return cb({ code: 200, msg: 'success', data: userInfo });
  } catch (e) {
    console.log(e);
    return cb({ code: 500, msg: 'error', data: [] });
  }
};

/**
 * @description: 登录用户查询
 * @param { string } username
 * @param { string } password
 * @return: cb
 */
exports.findUserForLogin = async function (user, ipAddr, cb) {
  const { username, password, os, browser } = user;
  const loginInfo = { loginName: username, ipAddr, browser, os };
  try {
    //检索用户
    const user = await SysUser.findOne({
      where: { username },
    });
    if (user === null) {
      const message = '用户名或密码输入错误！';
      SysLoginLog.addLoginLog({ ...loginInfo, state: 1, message: message });
      return cb({ code: 422, msg: message, data: {} });
    }
    if (user.status !== '0') {
      const message = '当前用户已被停用！';
      SysLoginLog.addLoginLog({ ...loginInfo, state: 1, message: message });
      return cb({ code: 422, msg: message, data: {} });
    }
    //验证用户密码
    const salt = user.salt;
    const cryptogram = ep.$sha1(ep.$md5(password) + salt);
    const isCorrect = user.password === cryptogram;

    //如果验证失败，返回错误
    if (isCorrect) {
      const { id, username, password, salt } = user;
      const userData = ep.$sha1(ep.$md5(username + password) + id + salt);
      // 将用户id传入并生成token
      let jwt = new JwtUtil(userData);
      let token = jwt.generateToken();
      const message = 'success';
      SysLoginLog.addLoginLog({ ...loginInfo, userId: id, state: 0, message });
      // 将 token 返回给客户端
      return cb({
        code: 200,
        msg: message,
        data: { token, sysUser: user, loginTime: moment() },
      });
    } else {
      const message = '用户名或密码输入错误！';
      SysLoginLog.addLoginLog({
        ...loginInfo,
        userId: user.id,
        state: 1,
        message,
      });
      return cb({ code: 422, msg: message, data: {} });
    }
  } catch (e) {
    //未知异常
    console.log(e);
    const message = '系统运行时异常';
    SysLoginLog.addLoginLog({ ...loginInfo, state: 1, message: message });
    return cb({ code: 500, msg: message, data: {} });
  }
};

/**
 * @description: 刷新 token
 * @param { string } token
 * @param { string } loginTime
 * @return: cb
 */
exports.refreshToken = async function (userinfo, loginTime, cb) {
  const currentTime = moment();
  const dateDiff = currentTime.diff(moment(loginTime), 'minutes');
  // 允许 Token 在过期的 30 分钟内重新获取 token
  if (loginTime === '' || dateDiff > 60) {
    return cb({ code: 409, msg: '身份认证已过期,请重新登录!', data: {} });
  }
  const { username,password } = userinfo;
  const user = await SysUser.findOne({ where: { username,password }  });
  if(user === null){
    return cb({ code: 409, msg: '用户信息已过期,请重新登录!', data: {} });
  }
  try {
    const userData = ep.$sha1(ep.$md5(username + password) + user.id + user.salt);
    const jwt = new JwtUtil(userData);
    const newToken = jwt.generateToken();
    return cb({
      code: 200,
      msg: 'success',
      data: { token: newToken, loginTime: currentTime },
    });
  } catch (e) {
    //未知异常
    console.log(e);
    return cb({ code: 409, msg: '身份认证失败，请重新登录！', data: {} });
  }
};

/**
 * @description 根据用户名查询用户
 * @param { string } username
 * @return cb
 */
exports.findUserByUsername = async function (username, cb) {
  try {
    //检索用户
    const user = await SysUser.findOne({ where: { username } });
    if (!user) {
      return cb({ code: 422, msg: '用户不存在！', data: [] });
    }
    return cb({ code: 200, msg: 'success', data: user });
  } catch (e) {
    //未知异常
    console.log(e);
    return cb({ code: 500, msg: 'error', data: [] });
  }
};

/**
 * @description 根据用户 ID 查询用户
 * @param { Number } id
 * @return cb
 */
exports.findUserInfoById = async function (id, cb) {
  try {
    //检索用户
    const user = await SysUser.findOne({ where: { id } });
    if (!user) {
      return cb({ code: 422, msg: '用户不存在！', data: [] });
    }
    return cb({ code: 200, msg: 'success', data: user });
  } catch (e) {
    //未知异常
    console.log(e);
    return cb({ code: 500, msg: 'error', data: [] });
  }
};

/**
 * @description:添加新用户
 * @param { Object } userInfo
 * @param { Function } cb
 * @return:cb
 */
exports.addUser = async function (userInfo, cb) {
  try {
    const user = await SysUser.findOne({
      where: {
        [Op.or]: {
          username: userInfo.username,
          email: userInfo.email,
          phone: userInfo.phone,
        },
      },
    });
    if (user?.username === userInfo.username) {
      return cb({ code: 422, msg: '登录名已被占用！', data: [] });
    } else if (user?.email === userInfo.email) {
      return cb({ code: 422, msg: '邮箱已被占用！', data: [] });
    } else if (user?.phone === userInfo.phone) {
      return cb({ code: 422, msg: '手机已被占用！', data: [] });
    }
  } catch (e) {
    console.log(e);
    return cb({ code: 500, msg: '系统繁忙，请稍后再试！', data: [] });
  }
  try {
    if (userInfo.birthday === '') {
      // 0001-01-01 在 mysql 中是 0000-12-31
      userInfo.birthday = '0001-01-01';
    }
    await SysUser.create(userInfo);
    return cb({ code: 200, msg: 'success' });
  } catch (e) {
    console.log(e);
    const message = ormErrorMessage(e);
    return cb({ code: 500, msg: message });
  }
};

/**
 * @description:根据ID 更新用户
 * @param { Number } id
 * @param { String } userinfo
 * @param { Function } cb
 * @return:cb
 */
exports.updatedUserById = async function (id, updateInfo, cb) {
  try {
    const user = await SysUser.findOne({ where: { id } });
    if (!user) {
      return cb({ code: 422, msg: '用户不存在！' });
    }
    try {
      const infoIsObject = updateInfo instanceof Object;
      const userinfo = infoIsObject ? updateInfo : JSON.parse(updateInfo);
      Object.keys(userinfo).forEach((item) => {
        user[item] = userinfo[item];
      });
      await user.save();
      return cb({ code: 200, msg: 'success' });
    } catch (e) {
      console.log(e);
      return cb({ code: 500, msg: '用户更新失败！' });
    }
  } catch (e) {
    console.log(e);
    return cb({ code: 500, msg: 'error' });
  }
};

/**
 * @description:根据ID删除用户
 * @param { Number } id
 * @param { Function } cb
 * @return:cb
 */
exports.deleteUserById = async function (id, cb) {
  try {
    const user = await SysUser.findOne({ where: { id } });
    if (!user) {
      return cb({ code: 422, msg: '用户不存在！' });
    }
    try {
      await user.destroy();
      return cb({ code: 200, msg: '用户删除成功！' });
    } catch (e) {
      console.log(e);
      return cb({ code: 500, msg: '用户删除失败！' });
    }
  } catch (e) {
    console.log(e);
    return cb({ code: 500, msg: 'error' });
  }
};

/**
 * @description:根据用户ID 重置用户密码
 * @param { Number } id
 * @param { Function } cb
 * @return:cb
 */
exports.resetPasswordById = async function (id, cb) {
  try {
    const user = await SysUser.findOne({ where: { id } });
    if (!user) {
      return cb({ code: 422, msg: '用户不存在！' });
    }
    try {
      // 触发 orm set 方法，重新设置新的盐值
      user.salt = true;
      // 如果要更新盐值，需要先保存盐值的更新，否则密码只能获取更新前的盐值
      const newSaltUser = await user.save();
      // 初始化密码为 123456
      newSaltUser.password = '123456';
      await newSaltUser.save();
      return cb({ code: 200, msg: 'success' });
    } catch (e) {
      console.log(e);
      return cb({ code: 500, msg: 'delete error' });
    }
  } catch (e) {
    console.log(e);
    return cb({ code: 500, msg: 'error' });
  }
};

/**
 * @description:根据用户ID 重置用户密码
 * @param { Number } id
 * @param { Function } cb
 * @return:cb
 */
exports.changePasswordById = async function (id,password,cb) {
  const {currentPassword,newPassword,repeat_password} = password;
  if(newPassword !== repeat_password){
    return cb({ code: 422, msg: '新密码和验证密码填写不一致！' });
  }
  const user = await SysUser.findOne({ where: { id } });
  //验证用户密码
  const salt = user.salt;
  const cryptogram = ep.$sha1(ep.$md5(currentPassword) + salt);
  const isCorrect = user.password === cryptogram;
  if(!isCorrect){
    return cb({ code: 422, msg: '当前密码不正确！' });
  }
  try{
    user.password = newPassword;
    await user.save()
    return cb({ code: 200, msg: '密码更新成功！' });
  }catch(e){
    console.log(e);
    return cb({ code: 500, msg: '密码更新失败！' });
  }
}